#pragma once 
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include<unistd.h>
#include <iostream>
#include <string>

#include "Log.hpp"

enum {
    USAG_ERR = 1,
    SOCK_ERR,
    BIND_ERR,
    LSITEN_ERR
};
#define PORT 8080

namespace wyl
{
    class TcpServer
    {
    public:
        TcpServer(uint16_t port = PORT) : _list_sock(-1),_port(port){}
        ~TcpServer(){close(_list_sock);}

        void init()
        {
            //1.创建套接字
            _list_sock = socket(AF_INET,SOCK_STREAM,0);
            if(_list_sock < 0)
            {
                logMessage(FATAL,"listsock created fail: %d",_list_sock);
                exit(SOCK_ERR);
            }
            logMessage(NORMAL,"listsock created success: %d",_list_sock);

            //2.绑定套接字
            struct sockaddr_in svr;
            svr.sin_port = htons(_port); 
            svr.sin_addr.s_addr = INADDR_ANY;
            svr.sin_family = AF_INET; 
            if(bind(_list_sock,(struct sockaddr*)&svr,sizeof svr) != 0)
            {
                logMessage(FATAL,"listsock bind fail");
                exit(BIND_ERR);
            }
            logMessage(NORMAL,"listsock bind success: %d",_list_sock);

            //3.监听套接字
            if(listen(_list_sock,5) != 0)
            {
                logMessage(FATAL,"listsock listen fail");
                exit(LSITEN_ERR);
            }
            logMessage(NORMAL,"listsock listen success: %d",_list_sock);
        }

        void start()
        {
            while(1)
            {
                //Accept获取连接，没有连接到来则阻塞
                struct sockaddr_in peer;
                socklen_t peer_len = sizeof peer;
                int new_sock = accept(_list_sock,(struct sockaddr*)&peer,&peer_len);
                if(new_sock < 0)
                {
                    logMessage(WARING,"listsock accept fail");
                    continue;
                }
                logMessage(NORMAL,"accept success  new sock : %d",new_sock);
                //为new_sock提供IO服务
                if(fork() == 0)
                {
                    close(_list_sock);
                    if(fork() > 0) exit(0);
                    IOServer(new_sock);
                    close(new_sock);
                    exit(0);
                }
                close(new_sock);
            }
        }
    private:
        void IOServer(int sock)
        {
            char buff[1024] = {0};
            for(; ;)
            {
                //读数据
                int n = read(sock,buff,sizeof buff-1); 
                if(n > 0)
                {
                    buff[n] = 0;
                    std::string message = "[Server Echo] :"; 
                    message += buff; 
                    std::cout << "clinet : " << buff << std::endl;
                    write(sock,message.c_str(),message.size()); //写数据
                }
                else if(n == 0)
                {
                    logMessage(NORMAL,"client quit... me too"); 
                    return;
                }else 
                {   
                    logMessage(ERROR,"read failed..... sock : %d",sock); 
                    return;
                }
            }
        }

    private:
        int _list_sock; 
        int _port;
    };
};